class_name ObjPool
extends Object



enum ObjState {
    IDLE,
    USING,
}



class ObjStateData extends Object:
    
    var state: ObjState = ObjState.IDLE:
        set(value):
            if value == state:
                return
            state = value
            state_changed.emit(state)
    
    signal state_changed(curr_state)




var _idle_objs: Array[Node]
var _using_objs: Array[Node]
var _index: int

signal has_obj_idled(obj)
signal has_obj_used(obj)




func _on_obj_state_changed(curr_state: ObjState, obj: Node) -> void:
    if curr_state == ObjState.IDLE:
        _using_objs.erase(obj)
        _idle_objs.push_front(obj)
        has_obj_idled.emit(obj)
    else:
        _idle_objs.erase(obj)
        _using_objs.push_front(obj)
        has_obj_used.emit(obj)


func create_objs_by_class(clazz, count: int, init_func: Callable = func(_obj):pass) -> void:
    for i in range(count):
        var obj = clazz.new()
        init_func.call(obj)
        var data := ObjStateData.new()
        data.state_changed.connect(_on_obj_state_changed.bind(obj))
        obj.set_meta("state_data", data)
        _idle_objs.append(obj)


func create_objs_by_packed_scene(scene: PackedScene, count: int, init_func: Callable = func(_obj):pass) -> void:
     for i in range(count):
        var obj = scene.instantiate()
        init_func.call(obj)
        var data := ObjStateData.new()
        data.state_changed.connect(_on_obj_state_changed.bind(obj))
        obj.set_meta("state_data", data)
        _idle_objs.append(obj)


func get_obj() -> Node:
    var obj = _idle_objs.front()
    if obj == null:
        return null
    obj.get_meta("state_data").state = ObjState.USING
    return obj


static func idle(obj: Node) -> void:
    var data = obj.get_meta("state_data")
    if data == null: return
    data.state = ObjState.IDLE
    var parent := obj.get_parent()
    if parent:
        parent.remove_child(obj)

